//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "cevent.h"
#include "cthread.h"
#include "pseudo.h"
#include "helper.h"
#include <aura.h>
#include <elacs.h>

CEvent::~CEvent()
{
    if (NULL != m_hEvent) {
        AuraEvent_Destroy(m_hEvent);
        m_hEvent = NULL;
    }
}

ECode CEvent::Initialize(
    /* [in] */ Boolean bManualReset,
    /* [in] */ EventState initialState)
{
    return AuraEvent_Create(bManualReset, initialState, &m_hEvent);
}

PInterface CEvent::Probe(
    /* [in]  */ REIID riid)
{
    if (riid == EIID_IInterface) {
        return (PInterface)(IEvent *)this;
    }
    else if (riid == EIID_IEvent) {
        return (IEvent *)this;
    }
    else if (riid == EIID_CLASS_INFO) {
        return (PInterface)&ECLSID_CEvent;
    }
    else if (riid == EIID_INTERFACE_INFO) {
        return (PInterface)&EIID_IEvent;
    }

    return NULL;
}

UInt32 CEvent::AddRef()
{
    Int32 nRef = m_cRef.Increment();
    return (UInt32)nRef;
}

UInt32 CEvent::Release()
{
    Int32 nRef = m_cRef.Decrement();
    if (nRef == 0) {
        delete this;
    }
    return (UInt32)nRef;
}

ECode CEvent::Aggregate(
    /* [in]  */ AggregateType type,
    /* [in]  */ PInterface pObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CEvent::GetDomain(
    /* [out] */ PInterface * ppObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CEvent::Wait(
    /* [out] */ WaitResult * pResult,
    /* [out] */ EventState * pState)
{
    if (NULL == pResult) {
        return E_INVALID_ARGUMENT;
    }

    return TryWait(INFINITE, pResult, pState);
}

ECode CEvent::TryWait(
    /* [in]  */ Millisecond32 msTimeout,
    /* [out] */ WaitResult * pResult,
    /* [out] */ EventState * pState)
{
    EventState state;
    ECode ec = NOERROR;

    if (NULL == pResult) {
        return E_INVALID_ARGUMENT;
    }

    THREAD_START_SLEEP()
    {
        ec = AuraEvent_Wait(m_hEvent,
                    (Aura_Millisecond32)msTimeout,
                    (Aura_WaitResult *)pResult,
                    (Aura_EventState *)&state);
    }
    THREAD_END_SLEEP;

    if (SUCCEEDED(ec) && (NULL != pState)) {
        *pState = state;
    }

    return ec;
}

ECode CEvent::Notify(
    /* [in ] */ EventState dwState)
{
    if (UNSIGNALED == dwState) {
        return E_INVALID_ARGUMENT;
    }

    return AuraEvent_Signal(m_hEvent, dwState);
}

ECode CEvent::Clear()
{
    return AuraEvent_Unsignal(m_hEvent);
}

// static member function to create event.-----
ECode CEvent::S_Create(
    /* [in] */ Boolean bManualReset,
    /* [in] */ EventState initialState,
    /* [out] */ IEvent ** ppEvent)
{
    CEvent * pEvent = NULL;
    ECode ec = NOERROR;

    assert(NULL != ppEvent);

    pEvent = new CEvent();
    if (NULL == pEvent) {
        ec = E_OUT_OF_MEMORY;
        goto ErrorExit;
    }
    ec = pEvent->Initialize(bManualReset, initialState);
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    pEvent->AddRef();

    *ppEvent = static_cast<IEvent *>(pEvent);
    return NOERROR;

ErrorExit:
    if (NULL != pEvent) {
        delete pEvent;
    }
    return ec;
}

